
import cv2
from matplotlib import  pyplot as plt
class Opencv():
    def __init__(self,):
        pass
    def load_image(self,path):
        self.origin_img= cv2.imread(path)
        self.origin_img = self.origin_img[:,:,[2,1,0]]
        return self.origin_img
    def gray(self,path=None):
        if not path:
            img=self.origin_img
        else:
            img= self.load_image(path)
        return cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) 
    def blur(self):
        """实现平均滤波，高斯滤波及中值滤"""
        #中值滤波
        img=self.origin_img
        #plt.figure(figsize=(100,50))
        plt.subplot(321,figsize=(10, 5)),plt.imshow(img),plt.title('origin')
        retuan
        #plt.axis('off')
        img_medianBlur=cv2.medianBlur(img,5)
        plt.subplot(322),plt.imshow(img),plt.title('medianBlur')
        #cv2.imshow('medianBlur',img_medianBlur)
        #均值滤波
        img_Blur=cv2.blur(img,(5,5))
        plt.subplot(323),plt.imshow(img),plt.title('blur')
        #cv2.imshow('blur',blur)
        #高斯滤波
        img_GaussianBlur=cv2.GaussianBlur(img,(7,7),0)
        plt.subplot(324),plt.imshow(img),plt.title('GaussianBlur')
        #cv2.imshow('GaussianBlur',img_GaussianBlur)
        #高斯双边滤波 效果最柔顺
        img_bilateralFilter=cv2.bilateralFilter(img,40,75,75)
        plt.subplot(325),plt.imshow(img),plt.title('bilateralFilter')
        #cv2.imshow('bilateralFilter',img_bilateralFilter)
        plt.show()
    def soble_lg_cany(self):
  
        """以Lena为原始图像，通过OpenCV使用Sobel及Canny算子检测，比较边缘检测结果。"""
        img_gray=self.origin_img
          #from skimage import transform
            #dst=transform.resize(img, (80, 60))
        # sobel 算子 
        img_sobel_x = cv2.Sobel(img_gray, cv2.CV_64F, 1, 0, ksize=3)  
        img_sobel_y = cv2.Sobel(img_gray, cv2.CV_64F, 0, 1, ksize=3)
        absX = cv2.convertScaleAbs(img_sobel_x)   # 转回uint8  
        absY = cv2.convertScaleAbs(img_sobel_y)  
          
        dst = cv2.addWeighted(absX,0.5,absY,0.5,0)  
        # Laplace 算子  
        img_laplace = cv2.Laplacian(img_gray, cv2.CV_64F, ksize=3)  

        # Canny 算子  
        img_canny = cv2.Canny(img_gray, 100 , 150)
        plt.subplot(231), plt.imshow(img_gray, "gray"), plt.title("Original")  
        plt.subplot(232), plt.imshow(img_sobel_x, "gray"), plt.title("Sobel_x")  
        plt.subplot(233), plt.imshow(img_sobel_y, "gray"), plt.title("Sobel_y")
        plt.subplot(234), plt.imshow(dst, "gray"), plt.title("Sobel")  
        plt.subplot(235), plt.imshow(img_laplace,  "gray"), plt.title("Laplace")  
        plt.subplot(236), plt.imshow(img_canny, "gray"), plt.title("Canny")

        plt.show()
        cv2.imshow("Sobel", dst)
        cv2.imshow("img_canny", img_canny) 
        cv2.waitKey(0)
    def hits(self):
        """在OpenCV安装目录下找到课程对应演示图片(安装目录\sources\samples\data)，首先计算灰度直方图，进一步使用大津算法进行分割，并比较分析分割结果"""
        #https://www.cnblogs.com/FHC1994/p/9118351.html
        plt.hist(self.origin_img.ravel(), 256, [0, 256]) #ravel函数功能是将多维数组降为一维数组
        plt.show()
        color=['b','g','r']
        for i ,color in enumerate(color):
            hist=cv2.calcHist([self.origin_img],[i],None,[256],[0,256])
            plt.plot(hist,color)
            plt.xlim([0,256])
        plt.show()
    def ots(self,path):
        image= cv2.imread(path,0)
        plt.subplot(131), plt.imshow(image, "gray")

        plt.title("source image"), plt.xticks([]), plt.yticks([])
        plt.subplot(132), plt.hist(image.ravel(), 256)
        plt.title("Histogram")
        ret1, th1 = cv2.threshold(image, 0, 255, cv2.THRESH_BINARY+cv2.THRESH_OTSU)  #方法选择为THRESH_OTSU
        #ret1, th1 = cv2.threshold(image, 127, 255, cv2.THRESH_BINARY)  ##简单滤波
        #th2 = cv2.adaptiveThreshold(img,255,cv2.ADAPTIVE_THRESH_MEAN_C,cv2.THRESH_BINARY,11,2)

        plt.subplot(133), plt.imshow(th1, "gray")
        plt.title("OTSU,threshold is " + str(ret1)), plt.xticks([]), plt.yticks([])
        plt.show()
#https://docs.opencv.org/3.1.0/d7/d4d/tutorial_py_thresholding.html 文档
    def rice(self,path):
        image= cv2.imread(path,0)
        plt.subplot(151), plt.imshow(image, "gray"),plt.title("origin") 

        ret1, th1 = cv2.threshold(image, 0, 255, cv2.THRESH_BINARY+cv2.THRESH_OTSU) #大津算法阀值化
        plt.subplot(152), plt.imshow(th1, "gray"),plt.title("otsu")
        
        kernel = cv2.getStructuringElement(cv2.MORPH_RECT,(5, 5))
        
        #img = cv2.morphologyEx(th1, cv2.MORPH_CLOSE, kernel) #效果不好
        img = cv2.morphologyEx(th1, cv2.MORPH_OPEN, kernel)
        plt.subplot(153), plt.imshow(img, "gray"),plt.title("quzao")
        image,contours,hierarchv = cv2.findContours(img,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
        plt.subplot(154), plt.imshow(image, "gray"),plt.title("findContours")
        color = cv2.cvtColor(image, cv2.COLOR_GRAY2BGR)
        cv2.drawContours(color, contours, -1, (0, 255, 0),1)  # 画出轮廓，-1,表示所有轮廓，画笔颜色为(0, 255, 0)，即Green，粗细为3
        count=0
        area=0
        for i in contours:
            a=cv2.contourArea(i)
            if a>10:
                count+=1
                area+=a
                x, y, w, h = cv2.boundingRect(i)
                cv2.rectangle(color, (x, y), (x+w, y+h), (0, 255, 0), 3)
                #rect = cv2.minAreaRect(i)                
                #box = cv2.cv.BoxPoints(rect)                
                #cv2.drawContours(img, [box], 0, (0, 0, 255), 2)
        cv2.imshow('rectangle', color)
        #plt.subplot(155), plt.imshow(image, "gray"),plt.title("rectangle")
        plt.show()
    def orb(self,path):
        #https://blog.csdn.net/EDS95/article/details/70146689
        img = cv2.imread(path,0)
        orb = cv2.ORB_create()
        kp = orb.detect(img,None)
        kp, des = orb.compute(img, kp)
        img = cv2.drawKeypoints(img,kp,img,color=(0,255,0), flags=0)
        cv2.imshow('p',img)
        cv2.waitKey()
        
"""
3. 。 
4. 使用米粒图像，分割得到各米粒，首先计算各区域(米粒)的面积、长度等信息，进一步计算面积、长度的均值及方差，分析落在3sigma范围内米粒的数量。 
扩展作业： 
5. 使用棋盘格及自选风景图像，分别使用SIFT、FAST及ORB算子检测角点，并比较分析检测结果。 
(可选)使用Harris角点检测算子检测棋盘格，并与上述结果比较。 
#https://gitee.com/jpython/computer_vision_foundation
"""

if __name__=='__main__':
    c=Opencv()
    img_path="C:\\opencv\\opencv\\sources\\samples\\data\\rice.jpg"
    c.load_image(img_path)
    #c.blur()
    #c.soble_lg_cany()
    #c.hits()
    #c.ots(img_path)
    #c.rice(img_path)
    img_path="C:\\opencv\\opencv\\sources\\samples\\data\\right12.jpg"
    c.orb(img_path)
